-- SPDX-License-Identifier: GPL-3.0-or-later

local extension = Package("ling3")
extension.extensionName = "lingling"

local U = require "packages/utility/utility"

local liubang = General(extension, "lingling__liubang", "han", 4)
local huabing = fk.CreateTriggerSkill{
  name = "lingling__huabing",
  anim_type = "control",
  events = {fk.TurnEnd},
  can_trigger = function(self, event, target, player, data)
    return target == player and player:hasSkill(self) and
      table.find(player.room:getOtherPlayers(player), function (p)
        return p:getHandcardNum() > 1
      end)
  end,
  on_cost = function(self, event, target, player, data)
    local room = player.room
    local targets = table.filter(room:getOtherPlayers(player), function (p)
      return p:getHandcardNum() > 1
    end)
    local to = room:askForChoosePlayers(player, table.map(targets, Util.IdMapper), 1, 1,
      "#lingling__huabing-choose", self.name)
    if #to > 0 then
      self.cost_data = {tos = to}
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local to = room:getPlayerById(self.cost_data.tos[1])
    room:setPlayerMark(to, "@@lingling__huabing", 1)
    room:addTableMark(player, self.name, to.id)
    local cards = room:askForCardsChosen(player, to, 2, 2, "h", self.name, "#lingling__huabing-prey::"..to.id)
    room:moveCardTo(cards, Card.PlayerHand, player, fk.ReasonPrey, self.name, nil, false, player.id)
  end,
}
local huabing_delay = fk.CreateTriggerSkill{
  name = "#huabing_delay",
  anim_type = "control",
  events = {fk.TurnStart},
  can_trigger = function(self, event, target, player, data)
    return table.contains(player:getTableMark("lingling__huabing"), target.id)
  end,
  on_cost = Util.TrueFunc,
  on_use = function(self, event, target, player, data)
    local room = player.room
    room:setPlayerMark(target, "@@lingling__huabing", 0)
    room:removeTableMark(player, "lingling__huabing", target.id)
    local choices = {"lingling__huabing2::"..target.id}
    if not target.dead then
      table.insert(choices, "lingling__huabing1::"..target.id)
    end
    local choice = room:askForChoice(player, choices, "lingling__huabing")
    if choice[18] == "1" then
      player:drawCards(1, "lingling__huabing")
      if not player.dead and not target.dead and not player:isNude() then
        local cards = {}
        if #player:getCardIds("he") > 2 then
          cards = room:askForCard(player, 3, 3, true, "lingling__huabing", false, nil, "#lingling__huabing-give::"..target.id)
        else
          cards = player:getCardIds("he")
        end
        room:moveCardTo(cards, Card.PlayerHand, target, fk.ReasonGive, "lingling__huabing", nil, false, player.id)
      end
    else
      room:damage{
        from = target,
        to = player,
        damage = 1,
        skillName = "lingling__huabing",
      }
    end
  end,
}
local fengeng = fk.CreateTriggerSkill{
  name = "lingling__fengeng",
  anim_type = "support",
  events = {fk.CardUseFinished},
  can_trigger = function(self, event, target, player, data)
    return player:hasSkill(self) and target ~= player and (data.card.trueName == "peach" or data.card.trueName == "ex_nihilo") and
      data.card.skill:canUse(player, Fk:cloneCard(data.card.name)) and
      player:getMark("lingling__fengeng_"..data.card.trueName.."-round") == 0 and not player:isNude()
  end,
  on_cost = function(self, event, target, player, data)
    local room = player.room
    local cards = table.filter(player:getCardIds("he&"), function (id)
      local card = Fk:cloneCard(data.card.name)
      card.skillName = self.name
      card:addSubcard(id)
      return card.skill:canUse(player, card)
    end)
    local card = room:askForCard(player, 1, 1, true, self.name, true, tostring(Exppattern{ id = cards }),
      "#lingling__fengeng-invoke:::"..data.card.name)
    if #card > 0 then
      self.cost_data = {cards = card}
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    room:setPlayerMark(player, "lingling__fengeng_"..data.card.trueName.."-round", 1)
    room:useVirtualCard(data.card.name, self.cost_data.cards, player, player, self.name)
  end,
}
huabing:addRelatedSkill(huabing_delay)
liubang:addSkill(huabing)
liubang:addSkill(fengeng)
Fk:loadTranslationTable{
  ["lingling__liubang"] = "刘邦",
  ["#lingling__liubang"] = "天阶三尺",
  ["illustrator:lingling__liubang"] = "珊瑚虫",
  ["designer:lingling__liubang"] = "伶",

  ["lingling__huabing"] = "画饼",
  [":lingling__huabing"] = "回合结束时，你可以获得一名其他角色两张手牌，然后其下回合开始时你选择：摸一张牌并交给其三张牌；受到其造成的1点伤害。",
  ["lingling__fengeng"] = "分羹",
  [":lingling__fengeng"] = "每轮各限一次，当其他角色使用【桃】或【无中生有】后，你可以将一张牌当同名牌使用。"..
  "<br><br> <font color = '#a40000'>汉祖之神圣，尧以后一人也。",
  ["#lingling__huabing-choose"] = "画饼：你可以获得一名角色两张手牌，其下回合开始时你选择一项",
  ["#lingling__huabing-prey"] = "画饼：获得 %dest 两张手牌",
  ["@@lingling__huabing"] = "画饼",
  ["#huabing_delay"] = "画饼",
  ["lingling__huabing1"] = "摸一张牌并交给 %dest 三张牌",
  ["lingling__huabing2"] = "%dest 对你造成1点伤害",
  ["#lingling__huabing-give"] = "画饼：请交给 %dest 三张牌",
  ["#lingling__fengeng-invoke"] = "分羹：你可以将一张牌当【%arg】使用",
}

local liuche = General(extension, "lingling__liuche", "han", 5)
local kouluan = fk.CreateTriggerSkill{
  name = "lingling__kouluan",
  anim_type = "special",
  frequency = Skill.Compulsory,
  events = {fk.GameStart},
  can_trigger = function(self, event, target, player, data)
    return player:hasSkill(self)
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local cards = U.prepareDeriveCards(room, {
      {"savage_assault", Card.Spade, 7}, --{"savage_assault", Card.Spade, 7},
      {"savage_assault", Card.Club, 7}, --{"savage_assault", Card.Club, 7},
      {"savage_assault", Card.Spade, 13}, {"savage_assault", Card.Spade, 13},
    }, self.name)
    for _, id in ipairs(cards) do
      if room:getCardArea(id) == Card.Void then
        table.removeOne(room.void, id)
        table.insert(room.draw_pile, math.random(1, #room.draw_pile // 2), id)
        room:setCardArea(id, Card.DrawPile, nil)
      end
    end
    room:doBroadcastNotify("UpdateDrawPile", tostring(#room.draw_pile))
  end,
}
local jibei = fk.CreateTriggerSkill{
  name = "lingling__jibei",
  mute = true,
  events = {fk.CardUseFinished, fk.AfterCardsMove},
  can_trigger = function(self, event, target, player, data)
    if not player:hasSkill(self) then return end
    if event == fk.CardUseFinished then
      return data.card.trueName == "savage_assault" and not target.dead
    elseif event == fk.AfterCardsMove then
      for _, move in ipairs(data) do
        if move.toArea == Card.DiscardPile then
          for _, info in ipairs(move.moveInfo) do
            if Fk:getCardById(info.cardId).trueName == "savage_assault" then
              return true
            end
          end
        end
      end
    end
  end,
  on_trigger = function(self, event, target, player, data)
    if event == fk.CardUseFinished then
      self:doCost(event, target, player, data)
    elseif event == fk.AfterCardsMove then
      local i = 0
      for _, move in ipairs(data) do
        if move.toArea == Card.DiscardPile then
          for _, info in ipairs(move.moveInfo) do
            if Fk:getCardById(info.cardId).trueName == "savage_assault" then
              i = i + 1
            end
          end
        end
      end
      for _ = 1, i do
        if not player:hasSkill(self) then break end
        self:doCost(event, target, player, data)
      end
    end
  end,
  on_cost = function(self, event, target, player, data)
    if event == fk.CardUseFinished then
      if player.room:askForSkillInvoke(player, self.name, nil, "#lingling__jibei-damage::"..target.id) then
        self.cost_data = {tos = {target.id}}
        return true
      end
    elseif event == fk.AfterCardsMove then
      self.cost_data = nil
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    player:broadcastSkillInvoke(self.name)
    if event == fk.CardUseFinished then
      room:notifySkillInvoked(player, self.name, "offensive")
      room:damage{
        from = player,
        to = target,
        damage = 1,
        skillName = self.name,
      }
    elseif event == fk.AfterCardsMove then
      room:notifySkillInvoked(player, self.name, "drawcard")
      player:drawCards(2, self.name)
    end
  end,
}
liuche:addSkill(kouluan)
liuche:addSkill(jibei)
Fk:loadTranslationTable{
  ["lingling__liuche"] = "刘彻",
  ["#lingling__liuche"] = "功大威行",
  ["illustrator:lingling__liuche"] = "珊瑚虫",
  ["designer:lingling__liuche"] = "伶",

  ["lingling__kouluan"] = "寇乱",
  [":lingling__kouluan"] = "游戏开始时，在牌堆的前面一半额外加入4张【南蛮入侵】。",
  ["lingling__jibei"] = "击北",
  [":lingling__jibei"] = "当一名角色使用【南蛮入侵】结算后，你可以对其造成1点伤害。当一张【南蛮入侵】进入弃牌堆后，你摸两张牌。"..
  "<br><br> <font color = '#a40000'>寇可往，吾亦可往！",
  ["#lingling__jibei-damage"] = "击北：是否对 %dest 造成1点伤害？",
  ["#lingling__jibei-draw"] = "击北：是否摸两张牌？",
}

local liuxiu = General(extension, "lingling__liuxiu", "han", 3)
local qiangyun = fk.CreateTriggerSkill{
  name = "lingling__qiangyun",
  anim_type = "drawcard",
  frequency = Skill.Compulsory,
  events = {fk.DrawNCards},
  on_use = function(self, event, target, player, data)
    local room = player.room
    local n = math.random(6)
    room:sendLog({
      type = "#lingling__liuxiu_random",
      from = player.id,
      arg = n,
      toast = true,
    })
    if player.hp == 1 and room:askForSkillInvoke(player, self.name, nil, "#lingling__qiangyun-change:::"..n) then
      math.randomseed(tonumber(tostring(os.time()):reverse():sub(1, 6)))
      n = math.random(6)
      room:sendLog({
        type = "#lingling__liuxiu_random",
        from = player.id,
        arg = n,
        toast = true,
      })
    end
    data.n = n
  end,
}
local tianxuan = fk.CreateTriggerSkill{
  name = "lingling__tianxuan",
  anim_type = "defensive",
  frequency = Skill.Compulsory,
  events = {fk.DamageInflicted},
  can_trigger = function(self, event, target, player, data)
    return target == player and player:hasSkill(self) and data.damage >= player.hp + player.shield
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local n = math.random(6)
    room:sendLog({
      type = "#lingling__liuxiu_random",
      from = player.id,
      arg = n,
      toast = true,
    })
    if n == 6 and data.from and not data.from.dead then
      room:damage{
        to = data.from,
        damage = 2,
        skillName = self.name,
      }
    end
    if n > 3 then
      return true
    end
  end,
}
liuxiu:addSkill(qiangyun)
liuxiu:addSkill(tianxuan)
Fk:loadTranslationTable{
  ["lingling__liuxiu"] = "刘秀",
  ["#lingling__liuxiu"] = "允冠百王",
  ["illustrator:lingling__liuxiu"] = "珊瑚虫",
  ["designer:lingling__liuxiu"] = "伶",

  ["lingling__qiangyun"] = "强运",
  [":lingling__qiangyun"] = "摸牌阶段，你改为投掷一个6面骰子，然后摸点数张牌，若你体力为1则可以重新投掷一次。",
  ["lingling__tianxuan"] = "天选",
  [":lingling__tianxuan"] = "当你受到致命伤害时，你投掷一个6面骰子，若点数大于3则防止之，然后若点数为6则其受到2点无来源伤害。"..
  "<br><br> <font color = '#a40000'>驰驱铜马靖烟尘，命世英雄自有真。",
  ["#lingling__qiangyun-change"] = "强运：点数为%arg，是否要重投一次？",
  ["#lingling__liuxiu_random"] = "%from 掷骰子结果为：%arg",
}

local xiaohe = General(extension, "lingling__xiaohe", "han", 3)
local jimou = fk.CreateActiveSkill{
  name = "lingling__jimou",
  anim_type = "control",
  prompt = "#lingling__jimou",
  expand_pile = function(self)
    return Self:getTableMark(self.name)
  end,
  can_use = function (self, player, card, extra_data)
    return player:usedSkillTimes(self.name, Player.HistoryPhase) == 0
  end,
  card_num = 1,
  card_filter = function(self, to_select, selected)
    if #selected > 0 then return false end
    local mark = Self:getTableMark(self.name)
    if table.contains(mark, to_select) then
      local name = Fk:getCardById(to_select).name
      local card = Fk:cloneCard(name)
      card.skillName = self.name
      return card.skill:canUse(Self, card)
    end
  end,
  target_filter = function(self, to_select, selected, selected_cards)
    if #selected_cards == 0 then return end
    local card = Fk:cloneCard(Fk:getCardById(selected_cards[1]).name)
    card.skillName = self.name
    if #selected == 0 and to_select == Self.id then return end
    return card.skill:targetFilter(to_select, selected, {}, card)
  end,
  feasible = function(self, selected, selected_cards)
    if #selected_cards == 0 then return end
    local card = Fk:cloneCard(Fk:getCardById(selected_cards[1]).name)
    card.skillName = self.name
    return card.skill:feasible(selected, {}, Self, card)
  end,
  on_use = function(self, room, effect)
    local player = room:getPlayerById(effect.from)
    local target = room:getPlayerById(effect.tos[1])
    local card = Fk:cloneCard(Fk:getCardById(effect.cards[1]).name)
    card.skillName = self.name
    room:useCard{
      from = player.id,
      tos = table.map(effect.tos, function(id) return {id} end),
      card = card,
    }
    if target.dead then return end
    if not player.dead then
      local cards = table.filter(player:getTableMark(self.name), function (id)
        local card2 = Fk:getCardById(id)
        return card2.name ~= card.name and card2.skill:canUse(player, card2, {must_targets = {target.id}})
      end)
      if #cards > 0 then
        local dat = U.askForUseRealCard(room, player, cards, nil, self.name, "#lingling__jimou-use::"..target.id,
          {
            expand_pile = cards,
            bypass_times = true,
            must_targets = {target.id},
          }, true, false)
        if dat then
          local use = {
            card = Fk:cloneCard(dat.card.name),
            from = player.id,
            tos = dat.tos,
            extraUse = true,
          }
          use.card.skillName = self.name
          room:useCard(use)
        end
      end
    end
    if target.dead then return end
    room:addPlayerMark(target, "@lingling__jimou", 1)
    local n = 2 - target:getMark("lingling__jimou-tmp")
    room:setPlayerMark(target, "lingling__jimou-tmp", 0)
    if n > 0 then
      local cards = room:getCardsFromPileByRule("nullification", n, "allPiles")
      if #cards > 0 then
        room:moveCardTo(cards, Card.PlayerHand, target, fk.ReasonJustMove, self.name, nil, true, target.id)
      end
    end
  end,

  on_acquire = function (self, player, is_start)
    local room = player.room
    local cards = table.filter(U.getUniversalCards(room, "t"), function(id)
      local card = Fk:getCardById(id)
      return not card.multiple_targets and card.skill:getMinTargetNum() > 0
    end)
    room:setPlayerMark(player, self.name, cards)
  end,
}
local jimou_delay = fk.CreateTriggerSkill{
  name = "#lingling__jimou_delay",

  refresh_events = {fk.CardEffectCancelledOut, fk.TurnStart},
  can_refresh = function(self, event, target, player, data)
    if event == fk.CardEffectCancelledOut then
      return data.to and data.to == player.id and table.contains(data.card.skillNames, "lingling__jimou")
    elseif event == fk.TurnStart then
      return target == player and player:getMark("@lingling__jimou") > 0
    end
  end,
  on_refresh = function(self, event, target, player, data)
    local room = player.room
    if event == fk.CardEffectCancelledOut then
      room:addPlayerMark(player, "lingling__jimou-tmp", 1)
    elseif event == fk.TurnStart then
      room:addPlayerMark(player, MarkEnum.MinusMaxCards.."-turn", player:getMark("@lingling__jimou"))
      room:setPlayerMark(player, "@lingling__jimou", 0)
    end
  end,
}
local nadian = fk.CreateTriggerSkill{
  name = "lingling__nadian",
  anim_type = "drawcard",
  events = {fk.AfterCardsMove},
  can_trigger = function(self, event, target, player, data)
    if player:hasSkill(self) then
      local room = player.room
      local phase_event = room.logic:getCurrentEvent():findParent(GameEvent.Phase)
      if phase_event == nil or phase_event.data[2] ~= Player.Discard then return end
      local cards = {}
      for _, move in ipairs(data) do
        if move.from and move.from ~= player.id and move.moveReason == fk.ReasonDiscard then
          for _, info in ipairs(move.moveInfo) do
            if Fk:getCardById(info.cardId).type == Card.TypeTrick and table.contains(room.discard_pile, info.cardId) then
              table.insertIfNeed(cards, info.cardId)
            end
          end
        end
      end
      cards = U.moveCardsHoldingAreaCheck(room, cards)
      if #cards > 0 then
        self.cost_data = {cards = cards}
        return true
      end
    end
  end,
  on_use = function(self, event, target, player, data)
    player.room:moveCardTo(self.cost_data.cards, Card.PlayerHand, player, fk.ReasonJustMove, self.name, nil, true, player.id)
  end,
}
jimou:addRelatedSkill(jimou_delay)
xiaohe:addSkill(jimou)
xiaohe:addSkill(nadian)
Fk:loadTranslationTable{
  ["lingling__xiaohe"] = "萧何",
  ["#lingling__xiaohe"] = "开汉首功",
  ["illustrator:lingling__xiaohe"] = "珊瑚虫",
  ["designer:lingling__xiaohe"] = "伶",

  ["lingling__jimou"] = "急谋",
  [":lingling__jimou"] = "出牌阶段限一次，你可以视为对一名其他角色依次使用两张目标为唯一其他角色的牌名不同的普通锦囊牌，结算后其获得X张"..
  "【无懈可击】（X为生效牌数），且其下回合手牌上限-1。",
  ["lingling__nadian"] = "纳典",
  [":lingling__nadian"] = "其他角色于弃牌阶段弃置牌后，你可以获得其中所有锦囊牌。"..
  "<br><br> <font color = '#a40000'>相国人夸佐沛公，收图运饷守关中。<br>不知用蜀为根本，此是兴王第一功。",
  ["#lingling__jimou"] = "急谋：视为对一名角色依次使用两张锦囊，然后其获得生效牌数的【无懈可击】且其下回合手牌上限-1",
  ["#lingling__jimou-use"] = "急谋：再视为对 %dest 使用一张锦囊",
  ["@lingling__jimou"] = "急谋",
}

local hanxin = General(extension, "lingling__hanxin", "han", 4)
local dianbing = fk.CreateViewAsSkill{
  name = "lingling__dianbing",
  anim_type = "drawcard",
  pattern = "ex_nihilo",
  prompt = "#lingling__dianbing",
  card_filter = function(self, to_select, selected)
    return #selected == 0 and Fk:getCardById(to_select).trueName == "slash"
  end,
  view_as = function(self, cards)
    if #cards ~= 1 then return end
    local card = Fk:cloneCard("ex_nihilo")
    card.skillName = self.name
    card:addSubcard(cards[1])
    return card
  end,
  enabled_at_response = function(self, player, response)
    return not response
  end,
}
local dianbingExNihiloSkill = fk.CreateActiveSkill{
  name = "lingling__dianbing__ex_nihilo_skill",
  prompt = "#ex_nihilo_skill",
  mod_target_filter = Util.TrueFunc,
  can_use = function(self, player, card)
    return not player:isProhibited(player, card)
  end,
  on_use = function(self, room, cardUseEvent)
    if not cardUseEvent.tos or #TargetGroup:getRealTargets(cardUseEvent.tos) == 0 then
      cardUseEvent.tos = { { cardUseEvent.from } }
    end
  end,
  on_effect = function(self, room, effect)
    local target = room:getPlayerById(effect.to)
    if target.dead then return end
    local cards = target:drawCards(2, "ex_nihilo")
    if target.dead then return end
    if not table.find(cards, function (id)
      return Fk:getCardById(id).trueName == "slash"
    end) then
      room:invalidateSkill(target, "lingling__dianbing", "-turn")
    end
    cards = table.filter(cards, function (id)
      return table.contains(target:getCardIds("h"), id)
    end)
    if not target.dead and #cards > 0 then
      target:showCards(cards)
    end
  end
}
dianbingExNihiloSkill.cardSkill = true
Fk:addSkill(dianbingExNihiloSkill)
local dianbing_trigger = fk.CreateTriggerSkill{
  name = "#lingling__dianbing_trigger",

  refresh_events = {fk.PreCardEffect},
  can_refresh = function(self, event, target, player, data)
    return data.from == player.id and data.card.trueName == "ex_nihilo" and table.contains(data.card.skillNames, "lingling__dianbing")
  end,
  on_refresh = function(self, event, target, player, data)
    local card = data.card:clone()
    local c = table.simpleClone(data.card)
    for k, v in pairs(c) do
      card[k] = v
    end
    card.skill = dianbingExNihiloSkill
    data.card = card
  end,
}
local andu = fk.CreateTriggerSkill{
  name = "lingling__andu",
  events = {fk.EventPhaseEnd},
  anim_type = "offensive",
  can_trigger = function(self, event, target, player, data)
    if target == player and player:hasSkill(self) and player.phase == Player.Discard then
      local x = 0
      local logic = player.room.logic
      logic:getEventsOfScope(GameEvent.MoveCards, 1, function (e)
        for _, move in ipairs(e.data) do
          if move.from == player.id and move.moveReason == fk.ReasonDiscard and move.skillName == "phase_discard" then
            x = x + #move.moveInfo
            if x > 1 then return true end
          end
        end
        return false
      end, Player.HistoryTurn)
      return x > 1
    end
  end,
  on_cost = function(self, event, target, player, data)
    local room = player.room
    if not room.tag[self.name] then
      room:setPlayerMark(player, self.name, U.prepareDeriveCards(room,
        {
          {"slash", Card.NoSuit, 0},
          {"dismantlement", Card.NoSuit, 0},
        }, self.name))
    end
    local use = U.askForUseRealCard(room, player, room.tag[self.name], nil, self.name, "#lingling__andu-use",
      {
        expand_pile = room.tag[self.name],
        bypass_times = true,
      }, true, true)
    if use then
      self.cost_data = use
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local use = {
      card = Fk:cloneCard(self.cost_data.card.name),
      from = player.id,
      tos = self.cost_data.tos,
      extraUse = true,
    }
    use.card.skillName = self.name
    room:useCard(use)
  end,
}
dianbing:addRelatedSkill(dianbing_trigger)
hanxin:addSkill(dianbing)
hanxin:addSkill(andu)
Fk:loadTranslationTable{
  ["lingling__hanxin"] = "韩信",
  ["#lingling__hanxin"] = "国士无双",
  ["illustrator:lingling__hanxin"] = "珊瑚虫",
  ["designer:lingling__hanxin"] = "伶",

  ["lingling__dianbing"] = "点兵",
  [":lingling__dianbing"] = "你可以将【杀】当【无中生有】使用，然后展示获得的牌，若其中没有【杀】则此技能本回合无效。",
  ["lingling__andu"] = "暗度",
  [":lingling__andu"] = "弃牌阶段结束时，若你本阶段弃置了至少两张牌，你可以视为使用一张【杀】或【过河拆桥】。"..
  "<br><br> <font color = '#a40000'>昔者韩信将兵，无敌天下，功不世出，略不再见。",
  ["#lingling__dianbing"] = "点兵：你可以将【杀】当【无中生有】使用",
  ["#lingling__andu-use"] = "暗度：你可以视为使用一张【杀】或【过河拆桥】",
}

local zhangliangh = General(extension, "lingling__zhangliangh", "han", 3)
local wangshi = fk.CreateViewAsSkill{
  name = "lingling__wangshi",
  pattern = ".|.|.|.|.|trick|.",
  prompt = "#lingling__wangshi",
  interaction = function(self)
    local all_names = U.getAllCardNames("t")
    local names = U.getViewAsCardNames(Self, self.name, all_names, {}, Self:getTableMark("lingling__wangshi-turn"))
    if #names == 0 then return false end
    return U.CardNameBox { choices = names, all_choices = all_names }
  end,
  card_filter = function(self, to_select, selected)
    return #selected == 0 and Fk:getCardById(to_select).number > 9
  end,
  view_as = function(self, cards)
    if #cards ~= 1 or not self.interaction.data then return nil end
    local card = Fk:cloneCard(self.interaction.data)
    card:addSubcard(cards[1])
    card.skillName = self.name
    return card
  end,
  before_use = function(self, player, use)
    player.room:addTableMark(player, "lingling__wangshi-turn", use.card.trueName)
  end,
  enabled_at_response = function(self, player, response)
    if response then return end
    local all_names = U.getAllCardNames("t")
    local names = U.getViewAsCardNames(player, self.name, all_names, {}, player:getTableMark("lingling__wangshi-turn"))
    if #names == 0 then return end
    for _, name in ipairs(names) do
      local card = Fk:cloneCard(name)
      card.skillName = self.name
      if (Fk.currentResponsePattern == nil and player:canUse(card)) or
        (Fk.currentResponsePattern and Exppattern:Parse(Fk.currentResponsePattern):match(card)) then
        return true
      end
    end
  end,
}
local wangshi_trigger = fk.CreateTriggerSkill{
  name = "#lingling__wangshi_trigger",
  anim_type = "control",
  events = {fk.AfterCardUseDeclared},
  can_trigger = function(self, event, target, player, data)
    return target == player and player:hasSkill(wangshi) and data.card:isCommonTrick()
  end,
  on_cost = Util.TrueFunc,
  on_use = function(self, event, target, player, data)
    data.unoffsetableList = table.map(player.room.alive_players, Util.IdMapper)
  end,
}
local bianjing = fk.CreateTriggerSkill{
  name = "lingling__bianjing",
  anim_type = "control",
  events = {fk.DrawNCards},
  can_trigger = function(self, event, target, player, data)
    return target == player and player:hasSkill(self) and #player.room:getOtherPlayers(player) > 1
  end,
  on_cost = function(self, event, target, player, data)
    local room = player.room
    local tos = room:askForChoosePlayers(player, table.map(room:getOtherPlayers(player), Util.IdMapper), 2, 2,
      "#lingling__bianjing-choose", self.name, true)
    if #tos > 0 then
      room:sortPlayersByAction(tos)
      self.cost_data = {tos = tos}
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    data.n = 0
    player:drawCards(1, self.name)
    local targets = table.map(self.cost_data.tos, Util.Id2PlayerMapper)
    for _, p in ipairs(targets) do
      if not p.dead then
        p:drawCards(1, self.name)
      end
    end
    if targets[1].dead or targets[2].dead or not targets[1]:canPindian(targets[2]) then return end
    targets[1]:pindian({targets[2]}, self.name)
  end,
}
local bianjing_delay = fk.CreateTriggerSkill{
  name = "#lingling__bianjing_delay",
  mute = true,
  events = {fk.PindianResultConfirmed},
  can_trigger = function(self, event, target, player, data)
    if player:usedSkillTimes("lingling__bianjing", Player.HistoryPhase) > 0 and
      data.reason == "lingling__bianjing" and data.winner and
      not player.dead then
      self.cost_data = nil
      if data.winner == data.from then
        self.cost_data = data.fromCard
      else
        self.cost_data = data.toCard
      end
      return self.cost_data and player.room:getCardArea(self.cost_data) == Card.Processing
    end
  end,
  on_cost = Util.TrueFunc,
  on_use = function(self, event, target, player, data)
    player.room:moveCardTo(self.cost_data, Card.PlayerHand, player, fk.ReasonJustMove, "lingling__bianjing", nil, true, player.id)
  end,
}
wangshi:addRelatedSkill(wangshi_trigger)
bianjing:addRelatedSkill(bianjing_delay)
zhangliangh:addSkill(wangshi)
zhangliangh:addSkill(bianjing)
Fk:loadTranslationTable{
  ["lingling__zhangliangh"] = "张良",
  ["#lingling__zhangliangh"] = "元机孤映",
  ["illustrator:lingling__zhangliangh"] = "珊瑚虫",
  ["designer:lingling__zhangliangh"] = "伶",

  ["lingling__wangshi"] = "王师",
  [":lingling__wangshi"] = "每回合每种牌名限一次，你可以将点数不小于10的牌当任意普通锦囊牌使用。你使用锦囊牌无法被【无懈可击】响应。",
  ["lingling__bianjing"] = "辩经",
  [":lingling__bianjing"] = "摸牌阶段，你可以改为与两名其他角色各摸一张牌，然后他们拼点，你获得赢者拼点牌。"..
  "<br><br> <font color = '#a40000'>运筹策帷帐之中，决胜于千里之外。",
  ["#lingling__wangshi"] = "王师：你可以将一张点数不小于10的牌当任意普通锦囊牌使用",
  ["#lingling__wangshi_trigger"] = "王师",
  ["#lingling__bianjing-choose"] = "辩经：你可以改为与两名其他角色各摸一张牌，且令两者拼点，你获得赢者拼点牌",
}

local weiqing = General(extension, "lingling__weiqing", "han", 4)
local tianxing = fk.CreateViewAsSkill{
  name = "lingling__tianxing",
  anim_type = "offensive",
  pattern = "duel",
  prompt = function ()
    return "#lingling__tianxing:::"..Self:getMark("@lingling__tianxing")[1]
  end,
  times = function(self)
    return 2 - Self:usedSkillTimes(self.name, Player.HistoryTurn)
  end,
  card_filter = function(self, to_select, selected)
    return #selected < Self:getMark("@lingling__tianxing")[1]
  end,
  view_as = function(self, cards)
    if #cards ~= Self:getMark("@lingling__tianxing")[1] then return end
    local card = Fk:cloneCard("duel")
    card.skillName = self.name
    card:addSubcards(cards)
    return card
  end,
  after_use = function (self, player, use)
    if use.damageDealt then
      if not player.dead and table.find(TargetGroup:getRealTargets(use.tos), function (id)
        return use.damageDealt[id]
      end) then
        player:drawCards(player:getMark("@lingling__tianxing")[2], self.name)
      end
      if not player.dead and use.damageDealt[player.id] then
        player:drawCards(player:getMark("@lingling__tianxing")[3], self.name)
      end
    end
  end,
  enabled_at_play = function (self, player)
    return player:usedSkillTimes(self.name, Player.HistoryTurn) < 2
  end,
  enabled_at_response = function(self, player, response)
    return not response and player:usedSkillTimes(self.name, Player.HistoryTurn) < 2
  end,

  on_acquire = function (self, player, is_start)
    player.room:setPlayerMark(player, "@lingling__tianxing", {2, 1, 3})
  end,
  on_lose = function (self, player, is_death)
    player.room:setPlayerMark(player, "@lingling__tianxing", 0)
  end,
}
local tianxing_trigger = fk.CreateTriggerSkill{
  name = "#lingling__tianxing_trigger",

  refresh_events = {fk.TurnEnd},
  can_refresh = function(self, event, target, player, data)
    return target == player and player:hasSkill(tianxing, true)
  end,
  on_refresh = function (self, event, target, player, data)
    local mark = {1, 2, 3}
    table.shuffle(mark)
    player.room:setPlayerMark(player, "@lingling__tianxing", mark)
  end,
}
tianxing:addRelatedSkill(tianxing_trigger)
weiqing:addSkill(tianxing)
Fk:loadTranslationTable{
  ["lingling__weiqing"] = "卫青",
  ["#lingling__weiqing"] = "武烈长平",
  ["illustrator:lingling__weiqing"] = "珊瑚虫",
  ["designer:lingling__weiqing"] = "伶",

  ["lingling__tianxing"] = "天幸",
  [":lingling__tianxing"] = "每回合限两次，你可以将两张牌当【决斗】使用，若你因此对目标造成伤害，你摸一张牌，若你因此受到伤害，你摸三张牌。"..
  "回合结束时，随机互相调换此技能“一”、“两”、“三”的顺序。"..
  "<br><br> <font color = '#a40000'>但使龙城飞将在，不教胡马度阴山。",
  ["#lingling__tianxing"] = "天幸：你可以将%arg张牌当【决斗】使用",
  ["@lingling__tianxing"] = "天幸",
}

local huoqubing = General(extension, "lingling__huoqubing", "han", 4)
local shezi = fk.CreateActiveSkill{
  name = "lingling__shezi",
  anim_type = "drawcard",
  min_card_num = 1,
  target_num = 0,
  prompt = "#lingling__shezi",
  times = function(self)
    return Self.phase == Player.Play and 2 - Self:usedSkillTimes(self.name, Player.HistoryPhase) or -1
  end,
  can_use = function(self, player)
    return player:usedSkillTimes(self.name, Player.HistoryPhase) < 2
  end,
  card_filter = function(self, to_select, selected)
    return not Self:prohibitDiscard(Fk:getCardById(to_select))
  end,
  feasible = function (self, selected, selected_cards)
    local num = 0
    for _, id in ipairs(selected_cards) do
      num = num + Fk:getCardById(id).number
    end
    return num > 12
  end,
  on_use = function(self, room, effect)
    local player = room:getPlayerById(effect.from)
    local n = table.find(effect.cards, function (id)
      return Fk:getCardById(id).type == Card.TypeEquip
    end) and 3 or 2
    room:throwCard(effect.cards, self.name, player, player)
    if player.dead then return end
    player:drawCards(n, self.name)
  end,
}
local xiongzhu = fk.CreateTriggerSkill{
  name = "lingling__xiongzhu",
  anim_type = "offensive",
  events = {fk.CardUseFinished},
  can_trigger = function(self, event, target, player, data)
    return target == player and player:hasSkill(self) and not player:isNude() and player:getMark("@lingling__xiongzhu") < 13
  end,
  on_cost = function (self, event, target, player, data)
    local prompt = "#lingling__xiongzhu1"
    if player:getMark("@lingling__xiongzhu") > 0 then
      prompt = "#lingling__xiongzhu2:::"..(1 + player:getMark("@lingling__xiongzhu"))..":"..(2 + player:getMark("@lingling__xiongzhu"))
    end
    local success, dat = player.room:askForUseActiveSkill(player, "lingling__xiongzhu_viewas", prompt, true)
    if success and dat then
      self.cost_data = dat
      return true
    end
  end,
  on_use = function (self, event, target, player, data)
    local room = player.room
    local card = Fk.skills["lingling__xiongzhu_viewas"]:viewAs(self.cost_data.cards)
    room:setPlayerMark(player, "@lingling__xiongzhu", card.number)
    for _, id in ipairs(self.cost_data.targets) do
      room:addTableMark(player, "lingling__xiongzhu_prohibit-turn", id)
    end
    room:useCard{
      from = player.id,
      tos = table.map(self.cost_data.targets, function(id) return {id} end),
      card = card,
    }
  end,

  --[[refresh_events = {fk.Death},
  can_refresh = function(self, event, target, player, data)
    return player:getMark("@lingling__xiongzhu") > 0 and data.damage and data.damage.from and data.damage.from == player
  end,
  on_refresh = function(self, event, target, player, data)
    player.room:setPlayerMark(player, "@lingling__xiongzhu", 0)
  end,

  on_lose = function (self, player, is_death)
    player.room:setPlayerMark(player, "@lingling__xiongzhu", 0)
  end,]]--
}
local xiongzhu_viewas = fk.CreateViewAsSkill{
  name = "lingling__xiongzhu_viewas",
  card_filter = function(self, to_select, selected)
    if #selected == 0 then
      if Self:getMark("@lingling__xiongzhu") == 0 then
        return true
      else
        local n = Fk:getCardById(to_select).number - Self:getMark("@lingling__xiongzhu")
        return n == 1 or n == 2
      end
    end
  end,
  view_as = function(self, cards)
    if #cards ~= 1 then return end
    local card = Fk:cloneCard("unexpectation")
    card.skillName = "lingling__xiongzhu"
    card:addSubcard(cards[1])
    return card
  end,
}
local xiongzhu_prohibit = fk.CreateProhibitSkill{
  name = "#lingling__xiongzhu_prohibit",
  is_prohibited = function(self, from, to, card)
    return card and table.contains(card.skillNames, "lingling__xiongzhu") and
      table.contains(from:getTableMark("lingling__xiongzhu_prohibit-turn"), to.id)
  end,
}
Fk:addSkill(xiongzhu_viewas)
xiongzhu:addRelatedSkill(xiongzhu_prohibit)
huoqubing:addSkill(shezi)
huoqubing:addSkill(xiongzhu)
Fk:loadTranslationTable{
  ["lingling__huoqubing"] = "霍去病",
  ["#lingling__huoqubing"] = "封狼居胥",
  ["illustrator:lingling__huoqubing"] = "珊瑚虫",
  ["designer:lingling__huoqubing"] = "廷玉&伶",

  ["lingling__shezi"] = "舍辎",
  [":lingling__shezi"] = "出牌阶段限两次，你可以弃置任意张点数之和不小于13的牌并摸两张牌，若弃置了装备牌，额外摸一张牌。",
  ["lingling__xiongzhu"] = "雄逐",
  [":lingling__xiongzhu"] = "当你使用牌结算后，可以将一张牌当【出其不意】使用（每回合对每名角色限一次），若不为你第一次发动此技能，"..
  "用于转化的牌点数须比上一次发动此技能用于转化的牌点数大1或2。"..
  "<br><br> <font color = '#a40000'>先穷瀚海，再掀祁连。",
  ["#lingling__shezi"] = "舍辎：你可以弃置点数之和不小于13的牌，摸两张牌；若弃置装备牌则额外摸一张牌",
  ["#lingling__xiongzhu1"] = "雄逐：你可以将一张牌当【出其不意】使用",
  ["#lingling__xiongzhu2"] = "雄逐：你可以将一张点数为%arg或%arg2的牌当【出其不意】使用",
  ["@lingling__xiongzhu"] = "雄逐",
  ["lingling__xiongzhu_viewas"] = "雄逐",
}

local wangmang = General(extension, "lingling__wangmang", "xin", 4)
local daoxing = fk.CreateTriggerSkill{
  name = "lingling__daoxing",
  priority = 2,
  anim_type = "control",
  frequency = Skill.Compulsory,
  events = {fk.GameStart},
  can_trigger = function(self, event, target, player, data)
    return player:hasSkill(self)
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local availablePlayerIds = table.map(table.filter(room.players, function(p) return p.rest > 0 or not p.dead end), Util.IdMapper)
    local disabledPlayerIds = {}
    --[[if room:isGameMode("role_mode") then
      disabledPlayerIds = table.filter(availablePlayerIds, function(pid)
        local p = room:getPlayerById(pid)
        return p.role_shown and p.role == "lord"
      end)
    elseif room:isGameMode("1v2_mode") then
      local seat3Player = table.find(availablePlayerIds, function(pid)
        return room:getPlayerById(pid).seat == 3
      end)
      disabledPlayerIds = { seat3Player }
    end]]--

    local result = room:askForCustomDialog(
      player, self.name,
      "packages/lingling/qml/TaMoBox.qml",
      {
        availablePlayerIds,
        disabledPlayerIds,
        "$lingling__daoxing",
      }
    )
    result = json.decode(result)
    local players = table.simpleClone(room.players)
    for seat, playerId in pairs(result) do
      players[seat] = room:getPlayerById(playerId)
    end
    room.players = players
    local player_circle = {}
    for i = 1, #room.players do
      room.players[i].seat = i
      table.insert(player_circle, room.players[i].id)
    end
    for i = 1, #room.players - 1 do
      room.players[i].next = room.players[i + 1]
    end
    room.players[#room.players].next = room.players[1]
    room.current = room.players[1]
    room:doBroadcastNotify("ArrangeSeats", json.encode(player_circle))
  end,
}
local gengshi = fk.CreateTriggerSkill{
  name = "lingling__gengshi",
  anim_type = "control",
  frequency = Skill.Compulsory,
  events = {fk.Damage, fk.Damaged},
  can_trigger = function (self, event, target, player, data)
    return target == player and player:hasSkill(self) and
      not table.find(player.room.alive_players, function (p)
        return p.dying
      end)
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    player:drawCards(1, self.name)
    room.logic:breakTurn()
  end,
}
wangmang:addSkill(daoxing)
wangmang:addSkill(gengshi)
Fk:loadTranslationTable{
  ["lingling__wangmang"] = "王莽",
  ["#lingling__wangmang"] = "倒砌金塔",
  ["illustrator:lingling__wangmang"] = "珊瑚虫",
  ["designer:lingling__wangmang"] = "伶",

  ["lingling__daoxing"] = "倒行",
  [":lingling__daoxing"] = "游戏开始时，你重新调配所有角色的座次（行动顺序）。",
  ["lingling__gengshi"] = "更始",
  [":lingling__gengshi"] = "当你造成或受到伤害后，若没有角色处于濒死状态，你摸一张牌，停止一切结算，结束本回合。"..
  "<br><br> <font color = '#a40000'>我不属于这个时代。",
  ["$lingling__daoxing"] = "倒行",
}

local huoguang = General(extension, "lingling__huoguang", "han", 3)
local zhuanshan = fk.CreateActiveSkill{
  name = "lingling__zhuanshan",
  anim_type = "control",
  card_num = 0,
  target_num = 1,
  prompt = "#lingling__zhuanshan",
  can_use = function(self, player)
    return player:usedSkillTimes(self.name, Player.HistoryPhase) == 0
  end,
  card_filter = Util.FalseFunc,
  target_filter = function(self, to_select, selected)
    return #selected == 0 and to_select ~= Self.id
  end,
  on_use = function(self, room, effect)
    local player = room:getPlayerById(effect.from)
    local target = room:getPlayerById(effect.tos[1])
    if U.askForPlayCard(room, target, nil, ".|.|.|.|.|trick", self.name, "#lingling__zhuanshan-use:"..player.id) then
      if not player.dead then
        player:drawCards(2, self.name)
      end
    else
      if not table.contains(target.sealedSlots, Player.JudgeSlot) then
        room:addTableMark(player, self.name, target.id)
        room:addPlayerMark(player, MarkEnum.AddMaxCards, 2)
        room:addPlayerMark(target, MarkEnum.AddMaxCards, 2)
        local id = room:getNCards(1)[1]
        local card = Fk:cloneCard("indulgence")
        if Fk:getCardById(id, true).color == Card.Black then
          card = Fk:cloneCard("supply_shortage")
        end
        card:addSubcard(id)
        card.skillName = self.name
        target:addVirtualEquip(card)
        room:moveCardTo(card, Card.PlayerJudge, target, fk.ReasonJustMove, self.name, nil, true)
      end
    end
  end,
}
local zhuanshan_delay = fk.CreateTriggerSkill{
  name = "#lingling__zhuanshan_delay",

  refresh_events = {fk.AfterTurnEnd},
  can_refresh = function (self, event, target, player, data)
    return table.contains(player:getTableMark("lingling__zhuanshan"), target.id)
  end,
  on_refresh = function(self, event, target, player, data)
    local room = player.room
    local mark = player:getMark("lingling__zhuanshan")
    for i = #mark, 1, -1 do
      if mark[i] == target.id then
        table.remove(mark, i)
      end
    end
    room:setPlayerMark(player, "lingling__zhuanshan", mark)
    room:removePlayerMark(player, MarkEnum.AddMaxCards, 2)
    room:removePlayerMark(target, MarkEnum.AddMaxCards, 2)
  end,
}
local feili = fk.CreateActiveSkill{
  name = "lingling__feili",
  anim_type = "big",
  card_num = 0,
  target_num = 1,
  prompt = "#lingling__feili",
  times = function(self)
    return Self.phase == Player.Play and 2 - Self:usedSkillTimes(self.name, Player.HistoryGame) or -1
  end,
  can_use = function(self, player)
    return player:usedSkillTimes(self.name, Player.HistoryGame) < 2 and player:usedSkillTimes(self.name, Player.HistoryPhase) == 0
  end,
  card_filter = Util.FalseFunc,
  target_filter = function(self, to_select, selected)
    return #selected == 0 and to_select ~= Self.id and not table.contains(Self:getTableMark(self.name), to_select)
  end,
  on_use = function(self, room, effect)
    local player = room:getPlayerById(effect.from)
    local target = room:getPlayerById(effect.tos[1])
    room:addTableMark(player, self.name, target.id)
    room:setPlayerProperty(target, "role_shown", true)
    room:broadcastProperty(target, "role")
    if target.role == "loyalist" and room:getLord() then
      local lord = room:getLord()
      target.role, lord.role = lord.role, target.role
      room:setPlayerProperty(target, "role_shown", true)
      room:broadcastProperty(target, "role")
      room:setPlayerProperty(lord, "role_shown", true)
      room:broadcastProperty(lord, "role")
      room:changeMaxHp(lord, -1)
      if not target.dead then
        room:changeMaxHp(target, 1)
        if target:isWounded() and not target.dead then
          room:recover{
            who = target,
            num = 1,
            recoverBy = player,
            skillName = self.name,
          }
        end
      end
    end
  end,
}
zhuanshan:addRelatedSkill(zhuanshan_delay)
huoguang:addSkill(zhuanshan)
huoguang:addSkill(feili)
Fk:loadTranslationTable{
  ["lingling__huoguang"] = "霍光",
  ["#lingling__huoguang"] = "摄君如芒",
  ["illustrator:lingling__huoguang"] = "珊瑚虫",
  ["designer:lingling__huoguang"] = "伶",

  ["lingling__zhuanshan"] = "专擅",
  [":lingling__zhuanshan"] = "出牌阶段限一次，你可以令一名其他角色可以使用一张锦囊牌，若其如此做，你摸两张牌；若其未如此做，"..
  "你将牌堆顶的牌置于其判定区，若为红色则视为【乐不思蜀】，若为黑色则视为【兵粮寸断】，然后你与其的手牌上限皆+2，直到其下回合结束。",
  ["lingling__feili"] = "废立",
  [":lingling__feili"] = "每局限两次，出牌阶段限一次，你可以选择一名未以此法选择过的其他角色，其亮出身份牌（若已亮出则跳过），若为忠臣，"..
  "你令主公减1点体力上限并令其与该忠臣交换身份牌，然后新的主公加1点体力上限并回复1点体力。"..
  "<br><br> <font color = '#a40000'>几度咸阳累积尸，尽缘丘冢似焉支。<br>覆车愁杀张车骑，印绶临身必十辞。",
  ["#lingling__zhuanshan"] = "专擅：令一名角色使用一张锦囊牌，若使用则你摸两张牌，若不使用则将延时锦囊置入其判定区",
  ["#lingling__zhuanshan-use"] = "专擅：使用一张锦囊牌，若使用则%src摸两张牌，否则将延时锦囊置入你的判定区",
  ["#lingling__feili"] = "废立：令一名角色亮出身份，若为忠臣，其成为主公！",
}

return extension
